/*
Pyxis 2.0
Copyright 2010-2011 Thomas W. Holtquist

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

using System;
using System.Collections;

using Microsoft.SPOT;

using Skewworks.Pyxis.EXT;
using Skewworks.Pyxis.GUI;

namespace Skewworks.Pyxis.GUI.Controls
{
    [Serializable]
    public delegate void MenuItemTap(object sender);

    public class ContextMenuItem : MarshalByRefObject
    {

        #region Variables

        private string _text;
        private bool _enabled;
        private bool _expanded = false;
        private ArrayList _items = new ArrayList();
        private ContextMenuItem _parent = null;
        private ContextMenu _container = null;
        private Bitmap _ico = null;
        private rect _Bounds = new rect(0, 0, 0, 0);
        private bool _visible = true;

        private object _tag;

        #endregion

        #region Events

        public event MenuItemTap tapEvent;

        /// <summary>
        /// Event for Taps
        /// </summary>
        /// <param name="sender"></param>
        protected virtual void MenuItemTap(Object sender)
        {
            if (tapEvent != null) tapEvent(sender);
        }

        #endregion

        #region Constructors

        public ContextMenuItem()
        {
            _text = "";
            _enabled = true;
        }

        public ContextMenuItem(string text)
        {
            _text = text;
            _enabled = true;
        }

        public ContextMenuItem(string text, Bitmap icon)
        {
            _text = text;
            _ico = icon;
            _enabled = true;
        }

        public ContextMenuItem(string text, bool enabled)
        {
            _text = text;
            _enabled = enabled;
        }

        public ContextMenuItem(string text, Bitmap icon, bool enabled)
        {
            _text = text;
            _ico = icon;
            _enabled = enabled;
        }

        #endregion

        #region Properties

        public object Tag
        {
            get { return _tag; }
            set { _tag = value; }
        }

        /// <summary>
        /// Returns the width of the text + 8 padding
        /// </summary>
        public int Width
        {
            get
            {
                if (_text == "-")
                {
                    // This is a menu separator!
                    return -1;
                }
                int width, height;
                FontManager.Arial.ComputeExtent(renderText, out width, out height);

                if (_ico != null)
                {
                    int iMod = (_text == String.Empty) ? 0 : 4;
                    return width + _ico.Width + iMod + 8;
                }

                return width + 8;
            }
        }

        /// <summary>
        /// Returns the height of the text + 8 padding
        /// </summary>
        public int Height
        {
            get
            {
                if (_text == "-")
                {
                    // This is a menu separator!
                    return 9;
                }
                int width, height;
                FontManager.Arial.ComputeExtent(_text, out width, out height);

                if (_ico != null)
                {
                    Bitmap bmp24 = (Bitmap)_ico;
                    if (bmp24.Height > height) height = bmp24.Height;
                }

                return height + 8;
            }
        }

        /// <summary>
        /// Gets/Sets enabled property
        /// </summary>
        public bool Enabled
        {
            get { return _enabled; }
            set
            {
                _enabled = value;
                UpdateRenderRequired();
            }
        }

        /// <summary>
        /// Gets the menu icon
        /// </summary>
        public Bitmap icon
        {
            get
            {
                return _ico;
            }
            set
            {
                if (value.Height > 16 || value.Width > 16) throw new Exception("Menu icons cannot be larger than 16x16");
                _ico = value;
                UpdateRenderRequired();
            }
        }

        /// <summary>
        /// Gets/Sets menu text
        /// </summary>
        public string Text
        {
            get { return _text; }
            set
            {
                _text = value;
                UpdateRenderRequired();
            }
        }

        /// <summary>
        /// Gets the text as it should be drawn
        /// </summary>
        protected internal string renderText
        {
            get
            {
                if (_parent == null) return _text;
                return (_items.Count > 0) ? _text + "  >" : _text;
            }
        }

        /// <summary>
        /// Get's the number of items
        /// </summary>
        public int ItemCount
        {
            get { return _items.Count; }
        }

        /// <summary>
        /// Returns a specific menu item
        /// </summary>
        /// <param name="index">Index of menu item to get</param>
        /// <returns></returns>
        public ContextMenuItem Item(int index)
        {
            return (ContextMenuItem)_items[index];
        }

        /// <summary>
        /// Gets/Sets expanded
        /// </summary>
        protected internal bool Expanded
        {
            get { return _expanded; }
            set { _expanded = value; }
        }

        /// <summary>
        /// Gets/Sets parent
        /// This will later be used for
        /// Bubble-Up events
        /// </summary>
        protected internal ContextMenuItem Parent
        {
            get { return _parent; }
            set { _parent = value; }
        }

        /// <summary>
        /// Gets/Sets the items Bounds on screen
        /// Used to track Taps
        /// </summary>
        protected internal rect Bounds
        {
            get { return _Bounds; }
            set { _Bounds = value; }
        }

        /// <summary>
        /// Gets/Sets visibility
        /// </summary>
        public bool Visible
        {
            get { return _visible; }
            set { _visible = value; }
        }

        internal int IconWidth
        {
            get
            {
                if (_ico == null) return 0;
                return _ico.Width;
            }
        }

        internal ContextMenu Container
        {
            get
            {
                if (_parent == null) return _container;
                return _parent.Container;
            }
            set { _container = value; }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Adds a new menu item
        /// </summary>
        /// <param name="menu"></param>
        public void AddItem(ContextMenuItem menu)
        {
            menu.Parent = this;
            _items.Add(menu);
        }

        /// <summary>
        /// Removes all menu items
        /// </summary>
        public void ClearItems()
        {
            _items.Clear();
        }

        /// <summary>
        /// Removes a menu item
        /// </summary>
        /// <param name="menu"></param>
        public void RemoveItem(ContextMenuItem menu)
        {
            menu.Parent = null;
            _items.Remove(menu);
        }

        /// <summary>
        /// Removes a menu item by it's index
        /// </summary>
        /// <param name="index"></param>
        public void RemoveAt(int index)
        {
            ContextMenuItem mnu = (ContextMenuItem)_items[index];
            mnu.Parent = null;
            _items.RemoveAt(index);
        }

        #endregion

        #region Internal Methods

        /// <summary>
        /// Used by the desktop to invoke tap events
        /// </summary>
        /// <param name="sender"></param>
        protected internal void invokeTap(object sender)
        {
            MenuItemTap(sender);
        }

        internal void DrawIcon(Bitmap bmp, int x, int y)
        {
            if (_ico == null) return;
            Bitmap bmp24 = (Bitmap)_ico;
            bmp.DrawImage(x, y, bmp24, 0, 0, bmp24.Width, bmp24.Height);
        }

        #endregion

        #region Private Methods

        private void UpdateRenderRequired()
        {
            if (Container == null) return;
            if (_parent == null)
            {
                if (_visible) Container.ChildRequestedRender();
            }
            else
            {
                if (_parent.Expanded && _visible) Container.ChildRequestedRender();
            }
        }

        #endregion

    }
}
